---
title: Print
description: A library that provides printing functionality for Android and iOS (AirPrint).
sourceCodeUrl: 'https://github.com/expo/expo/tree/main/packages/expo-print'
packageName: 'expo-print'
iconUrl: '/static/images/packages/expo-print.png'
platforms: ['android', 'ios', 'web']
---

import APISection from '~/components/plugins/APISection';
import { APIInstallSection } from '~/components/plugins/InstallSection';
import { SnackInline } from '~/ui/components/Snippet';

`expo-print` provides an API for Android and iOS (AirPrint) printing functionality.

## Installation

<APIInstallSection />

## Usage

<SnackInline label='Print usage' dependencies={['expo-print', 'expo-sharing']}>

```jsx
import * as React from 'react';
import { View, StyleSheet, Button, Platform, Text } from 'react-native';
import * as Print from 'expo-print';
import { shareAsync } from 'expo-sharing';

const html = `
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
  </head>
  <body style="text-align: center;">
    <h1 style="font-size: 50px; font-family: Helvetica Neue; font-weight: normal;">
      Hello Expo!
    </h1>
    <img
      src="https://d30j33t1r58ioz.cloudfront.net/static/guides/sdk.png"
      style="width: 90vw;" />
  </body>
</html>
`;

export default function App() {
  const [selectedPrinter, setSelectedPrinter] = React.useState();

  const print = async () => {
    // On iOS/android prints the given html. On web prints the HTML from the current page.
    /* @info */ await Print.printAsync({
      html,
      printerUrl: selectedPrinter?.url, // iOS only
    }); /* @end */
  };

  const printToFile = async () => {
    // On iOS/android prints the given html. On web prints the HTML from the current page.
    /* @info */ const { uri } = await Print.printToFileAsync({ html }); /* @end */
    console.log('File has been saved to:', uri);
    await shareAsync(uri, { UTI: '.pdf', mimeType: 'application/pdf' });
  };

  const selectPrinter = async () => {
    /* @info */ const printer = await Print.selectPrinterAsync(); // iOS only
    /* @end */
    setSelectedPrinter(printer);
  };

  return (
    <View style={styles.container}>
      <Button title="Print" onPress={print} />
      <View style={styles.spacer} />
      <Button title="Print to PDF file" onPress={printToFile} />
      {Platform.OS === 'ios' && (
        <>
          <View style={styles.spacer} />
          <Button title="Select printer" onPress={selectPrinter} />
          <View style={styles.spacer} />
          {selectedPrinter ? (
            <Text style={styles.printer}>{`Selected printer: ${selectedPrinter.name}`}</Text>
          ) : undefined}
        </>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    backgroundColor: '#ecf0f1',
    flexDirection: 'column',
    padding: 8,
  },
  spacer: {
    height: 8,
  },
  printer: {
    textAlign: 'center',
  },
});
```

</SnackInline>

## API

```js
import * as Print from 'expo-print';
```

<APISection packageName="expo-print" apiName="Print" />

## Local images

On iOS, printing from HTML source doesn't support local asset URLs (due to WKWebView limitations). Instead, images need to be converted to base64 and inlined into the HTML.

```js
import { Asset } from 'expo-asset';
import { printAsync } from 'expo-print';
import { manipulateAsync } from 'expo-image-manipulator';

async function generateHTML() {
  const asset = Asset.fromModule(require('../../assets/logo.png'));
  const image = await manipulateAsync(asset.localUri ?? asset.uri, [], { base64: true });
  return `
    <html>
      <img
        src="data:image/jpeg;base64,${image.base64}"
        style="width: 90vw;" />
    </html>
  `;
}

async function print() {
  const html = await generateHTML();
  await printAsync({ html });
}
```

## Page margins

**On iOS** you can set the page margins using the `margins` option:

```js
const { uri } = await Print.printToFileAsync({
  html: 'This page is printed with margins',
  margins: {
    left: 20,
    top: 50,
    right: 20,
    bottom: 100,
  },
});
```

If `useMarkupFormatter` is set to `true`, setting margins may cause a blank page to appear at the end of your printout. To prevent this, make sure your HTML string is a well-formed document, including `<!DOCTYPE html>` at the beginning of the string.

**On Android**, if you're using `html` option in `printAsync` or `printToFileAsync`, the resulting print might contain page margins (it depends on the WebView engine).
They are set by `@page` style block and you can override them in your HTML code:

```html
<style>
  @page {
    margin: 20px;
  }
</style>
```

See [`@page` documentation on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/@page) for more details.
